{% extends 'base.html' %} {% load static %} {% block title %}上传文件 - {{ code.title }}{% endblock %} {% block extra_css %}
<style>
    .upload-area {
        border: 2px dashed rgba(255, 215, 0, 0.5) !important;
        border-radius: 0.5rem;
        padding: 3rem;
        text-align: center;
        background-color: rgba(45, 55, 85, 0.3) !important;
        color: white !important;
        transition: all 0.3s ease;
        cursor: pointer;
    }

    .upload-area:hover {
        border-color: var(--primary-gold) !important;
        background-color: rgba(255, 215, 0, 0.1) !important;
    }

    .upload-area.dragover {
        border-color: #00ff88 !important;
        background-color: rgba(0, 255, 136, 0.1) !important;
    }

    .file-preview {
        max-height: 300px;
        overflow-y: auto;
        border: 1px solid rgba(255, 215, 0, 0.3) !important;
        border-radius: 0.375rem;
        padding: 1rem;
        background-color: rgba(45, 55, 85, 0.4) !important;
        color: white !important;
    }

    .file-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0.5rem;
        border-bottom: 1px solid rgba(255, 215, 0, 0.2) !important;
        color: white !important;
    }

    .file-item:last-child {
        border-bottom: none;
    }

    .file-info {
        display: flex;
        align-items: center;
        color: white !important;
    }

    .file-icon {
        margin-right: 0.5rem;
        color: rgba(255, 255, 255, 0.8) !important;
    }

    .file-size {
        color: rgba(255, 255, 255, 0.6) !important;
        font-size: 0.875rem;
    }

    .remove-file {
        color: #ff6b6b !important;
        cursor: pointer;
        padding: 0.25rem;
    }

    .remove-file:hover {
        color: #ff5252 !important;
    }

    .upload-instructions {
        margin-top: 1rem;
        padding: 1rem;
        background-color: rgba(45, 55, 85, 0.3) !important;
        border-radius: 0.375rem;
        color: white !important;
    }

    .supported-formats {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        margin-top: 0.5rem;
    }

    .format-badge {
        background-color: rgba(255, 215, 0, 0.8) !important;
        color: #333 !important;
        padding: 0.25rem 0.5rem;
        border-radius: 0.25rem;
        font-size: 0.75rem;
    }

    .upload-area h5 {
        color: white !important;
        margin-bottom: 1rem;
    }

    .upload-area .text-muted {
        color: rgba(255, 215, 0, 0.8) !important;
    }

    .file-preview h6 {
        color: var(--primary-gold) !important;
        margin-bottom: 1rem;
    }
</style>
{% endblock %} {% block content %}
<div class="container mt-4">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    <h4 class="mb-0">上传文件到 "{{ code.title }}"</h4>
                </div>
                <div class="card-body">
                    <form method="post" enctype="multipart/form-data" id="uploadForm">
                        {% csrf_token %}

                        <!-- 隐藏的文件输入字段 -->
                        <div style="display: none;">
                            {{ form.files }}
                        </div>

                        <!-- 拖拽上传区域 -->
                        <div class="upload-area" id="uploadArea">
                            <i class="fas fa-cloud-upload-alt fa-3x text-muted mb-3"></i>
                            <h5>拖拽文件或game文件夹到此处或点击选择文件</h5>
                            
                            <!-- 显示表单错误 -->
                            {% if form.files.help_text %}
                            <div class="form-text text-center mt-2">{{ form.files.help_text }}</div>
                            {% endif %} 
                            {% if form.files.errors %}
                            <div class="text-danger text-center mt-2">
                                {% for error in form.files.errors %}
                                <small>{{ error }}</small>
                                {% endfor %}
                            </div>
                            {% endif %}
                        </div>

                        <!-- 文件预览 -->
                        <div id="filePreview" class="file-preview mt-3" style="display: none">
                            <h6>选中的文件:</h6>
                            <div id="fileList"></div>
                        </div>

                        <!-- 表单错误 -->
                        {% if form.non_field_errors %}
                        <div class="alert alert-danger">{% for error in form.non_field_errors %} {{ error }} {% endfor %}</div>
                        {% endif %}

                        <!-- 提交按钮 -->
                        <div class="d-flex justify-content-between mt-4">
                            <a href="{% url 'codes:code_files' code.id %}" class="btn btn-secondary">
                                <i class="fas fa-arrow-left"></i> 取消
                            </a>
                            <button type="submit" class="btn btn-primary" id="submitBtn">
                                <i class="fas fa-upload"></i> 上传文件
                            </button>
                        </div>
                    </form>
                </div>
            </div>

            <!-- 上传说明 -->
            <div class="upload-instructions mt-4">
                <h6><i class="fas fa-info-circle"></i> 上传说明</h6>
                <ul class="mb-2">
                    <li>支持多个文件和文件夹同时上传</li>
                    <li>仅支持Python(.py)、JavaScript(.js)、TypeScript(.ts)、Lua(.lua)文件</li>
                    <li>支持目录层级结构，文件夹内的文件将保持原有结构</li>
                    <li>上传后可以在文件管理页面查看和管理所有文件</li>
                    <li>单个文件最大100KB</li>
                </ul>

                <div class="supported-formats">
                    <strong>支持的文件格式：</strong>
                    <span class="format-badge">.py</span>
                    <span class="format-badge">.js</span>
                    <span class="format-badge">.ts</span>
                    <span class="format-badge">.lua</span>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %} {% block extra_js %}
<script>
    document.addEventListener('DOMContentLoaded', function () {
        const uploadArea = document.getElementById('uploadArea');
        const fileInput = document.getElementById('id_files');

        const filePreview = document.getElementById('filePreview');
        const fileList = document.getElementById('fileList');
        const submitBtn = document.getElementById('submitBtn');

        let selectedFiles = [];

        // 拖拽功能
        uploadArea.addEventListener('dragover', function (e) {
            e.preventDefault();
            uploadArea.classList.add('dragover');
        });

        uploadArea.addEventListener('dragleave', function (e) {
            e.preventDefault();
            uploadArea.classList.remove('dragover');
        });

        uploadArea.addEventListener('drop', function (e) {
            e.preventDefault();
            uploadArea.classList.remove('dragover');

            // 检查是否有文件夹
            const items = e.dataTransfer.items;
            if (items && items.length > 0) {
                const filePromises = [];
                const processEntry = (entry, path = '') => {
                    return new Promise((resolve) => {
                        if (entry.isFile) {
                            entry.file((file) => {
                                // 创建一个新的File对象，保留路径信息
                                const fileWithPath = new File([file], file.name, { type: file.type });
                                fileWithPath.relativePath = '';
                                resolve(fileWithPath);
                            });
                        } else if (entry.isDirectory) {
                            const dirReader = entry.createReader();
                            const readEntries = () => {
                                dirReader.readEntries((entries) => {
                                    if (entries.length > 0) {
                                        const entryPromises = [];
                                        for (let i = 0; i < entries.length; i++) {
                                            entryPromises.push(processEntry(entries[i], path + entry.name + '/'));
                                        }
                                        Promise.all(entryPromises).then((files) => {
                                            resolve(files.flat());
                                        });
                                    } else {
                                        resolve([]);
                                    }
                                });
                            };
                            readEntries();
                        }
                    });
                };

                for (let i = 0; i < items.length; i++) {
                    const item = items[i];
                    if (item.kind === 'file') {
                        const entry = item.webkitGetAsEntry
                            ? item.webkitGetAsEntry()
                            : item.getAsEntry
                            ? item.getAsEntry()
                            : null;
                        if (entry) {
                            filePromises.push(processEntry(entry));
                        }
                    }
                }

                Promise.all(filePromises).then((filesArray) => {
                    const files = filesArray.flat();
                    handleFiles(files);
                });
            } else {
                // 回退到普通文件处理
                const files = Array.from(e.dataTransfer.files);
                handleFiles(files);
            }
        });

        // 点击上传区域选择文件
        uploadArea.addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation(); // 阻止事件冒泡
            
            // 检查点击的目标是否是文件输入字段本身
            if (e.target === fileInput) {
                return;
            }
            
            // 创建一个临时的文件输入来支持文件夹选择
            const tempInput = document.createElement('input');
            tempInput.type = 'file';
            tempInput.webkitdirectory = true;
            tempInput.multiple = true;
            tempInput.style.display = 'none';
            
            tempInput.addEventListener('change', function() {
                const files = Array.from(this.files);
                handleFiles(files);
                document.body.removeChild(tempInput);
            });
            
            document.body.appendChild(tempInput);
            tempInput.click();
        });

        // 文件选择事件
        fileInput.addEventListener('change', function () {
            const files = Array.from(this.files);
            handleFiles(files);
        });

        // 移除对原始文件输入字段的文件夹属性设置
        // 这样可以避免与表单提交冲突
        // fileInput.setAttribute('webkitdirectory', '');
        // fileInput.setAttribute('directory', '');
        fileInput.setAttribute('multiple', '');

        function handleFiles(files) {
            // 过滤文件，只允许后缀为py、js、ts、lua的文件
            const validFiles = files.filter((file) => {
                const extension = file.name.split('.').pop().toLowerCase();
                return ['py', 'js', 'ts', 'lua'].includes(extension);
            });

            // 为文件添加相对路径属性
            validFiles.forEach((file) => {
                // 如果文件有webkitRelativePath属性，使用它来设置相对路径
                if (file.webkitRelativePath) {
                    const pathParts = file.webkitRelativePath.split('/');
                    pathParts.pop(); // 移除最后一个元素(文件名)
                    file.relativePath = pathParts.length > 0 ? pathParts.join('/') + '/' : '';
                } else {
                    file.relativePath = '';
                }
            });

            selectedFiles = validFiles;

            // 将文件设置到实际的文件输入字段
            const dt = new DataTransfer();
            selectedFiles.forEach((file) => dt.items.add(file));
            fileInput.files = dt.files;

            updateFilePreview();
        }

        function updateFilePreview() {
            if (selectedFiles.length === 0) {
                filePreview.style.display = 'none';
                return;
            }

            filePreview.style.display = 'block';
            fileList.innerHTML = '';

            selectedFiles.forEach((file, index) => {
                const fileItem = document.createElement('div');
                fileItem.className = 'file-item';

                const fileInfo = document.createElement('div');
                fileInfo.className = 'file-info';

                const icon = getFileIcon(file.name);
                // 显示文件路径（如果有）
                const displayPath = file.relativePath ? file.relativePath + file.name : file.name;
                fileInfo.innerHTML = `
                <i class="${icon} file-icon"></i>
                <span>${displayPath}</span>
                <span class="file-size ms-2">(${formatFileSize(file.size)})</span>
            `;

                const removeBtn = document.createElement('i');
                removeBtn.className = 'fas fa-times remove-file';
                removeBtn.title = '移除文件';
                removeBtn.addEventListener('click', function () {
                    selectedFiles.splice(index, 1);

                    // 更新实际的文件输入字段
                    if (selectedFiles.length > 0) {
                        const dt = new DataTransfer();
                        selectedFiles.forEach((file) => dt.items.add(file));
                        fileInput.files = dt.files;
                    } else {
                        fileInput.value = '';
                    }

                    updateFilePreview();
                });

                fileItem.appendChild(fileInfo);
                fileItem.appendChild(removeBtn);
                fileList.appendChild(fileItem);
            });
        }

        function getFileIcon(filename) {
            const ext = filename.split('.').pop().toLowerCase();
            const iconMap = {
                py: 'fab fa-python',
                js: 'fab fa-js-square',
                java: 'fab fa-java',
                cpp: 'fas fa-code',
                c: 'fas fa-code',
                h: 'fas fa-code',
                hpp: 'fas fa-code',
                html: 'fab fa-html5',
                css: 'fab fa-css3-alt',
                json: 'fas fa-file-code',
                xml: 'fas fa-file-code',
                yaml: 'fas fa-file-code',
                yml: 'fas fa-file-code',
                md: 'fab fa-markdown',
                txt: 'fas fa-file-alt',
                zip: 'fas fa-file-archive',
            };
            return iconMap[ext] || 'fas fa-file';
        }

        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // 表单提交处理
        document.getElementById('uploadForm').addEventListener('submit', function (e) {
            // 检查是否有选中的文件
            if (selectedFiles.length === 0) {
                e.preventDefault();
                alert('请先选择要上传的文件');
                return false;
            }
            
            // 禁用提交按钮，防止重复提交
            submitBtn.disabled = true;
            submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 上传中...';

            // 添加提交超时处理
            setTimeout(function () {
                if (submitBtn.disabled) {
                    submitBtn.disabled = false;
                    submitBtn.innerHTML = '<i class="fas fa-upload"></i> 上传文件';
                }
            }, 10000); // 10秒后重新启用按钮
            
            // 标记这是文件上传操作
            sessionStorage.setItem('fileUploading', 'true');
        });

        // 检查是否是文件上传成功的消息
        const alerts = document.querySelectorAll('.alert-success');
        const isFileUpload = sessionStorage.getItem('fileUploading');
        if (alerts.length > 0 && isFileUpload) {
            // 清除标记
            sessionStorage.removeItem('fileUploading');
            // 如果是文件上传成功消息，3秒后自动跳转到文件列表
            setTimeout(function () {
                window.location.href = "{% url 'codes:code_files' code.id %}";
            }, 3000);
        }
    });
</script>
{% endblock %}
